local _M = {}
_M._VERSION = '0.0.1'

local ERRORINFO     = require('abtesting.error.errcode').info
local systemConf    = require('abtesting.utils.init')
local utils         = require('abtesting.utils.utils')

local prefixConf    = systemConf.prefixConf
local runtimeLib    = prefixConf.runtimeInfoPrefix

local fields        = systemConf.fields
local divConf       = systemConf.divConf

local areNULL       = utils.areNULL
local nullTable     = utils.nullTable

local shdict_expire = divConf.shdict_expire

_M.new = function(self, sharedDict)
    if not sharedDict then
        error{ERRORINFO.ARG_BLANK_ERROR, 'cache name valid from nginx.conf'}
    end

    self.cache = ngx.shared[sharedDict]
    if not self.cache then
        error{ERRORINFO.PARAMETER_ERROR, 'cache name [' .. sharedDict .. '] valid from nginx.conf'}
    end

    return setmetatable(self, { __index = _M } )
end

_M.getSwtich = function(self, hostname)
    local cache = self.cache
    local k_switch = runtimeLib .. ':' .. hostname .. ':' .. fields.switch
    local switch = cache:get(k_switch)
    return tonumber(switch)
end

--
--  fetch runtimeInfo of hostname
--	divModulename
--	divDataKey
--	userInfoModulename
--
_M.getRuntime = function(self, hostname)
    local cache = self.cache
    local prefix = runtimeLib .. ':' .. hostname

    local k_divModname = prefix .. ':' .. fields.divModulename
    local k_divDataKey = prefix .. ':' .. fields.divDataKey
    local k_userInfoModname = prefix .. ':' .. fields.userInfoModulename

    local divModulename, err1 = cache:get(k_divModname)
    local divDataKey, err2 = cache:get(k_divDataKey)
    local userInfoModulename, err3 = cache:get(k_userInfoModname)

    if areNULL(divModulename, divDataKey, userInfoModulename) then
        return false
    end

    local runtime = {}
    runtime[fields.divModulename] = divModulename
    runtime[fields.divDataKey] = divDataKey
    runtime[fields.userInfoModulename] = userInfoModulename

    return true, runtime
end

_M.setRuntime = function(self, hostname, runtime)
    local cache = self.cache
    local prefix = runtimeLib .. ':' .. hostname
    local expire = shdict_expire

    local k_switch = prefix .. ':' .. fields.switch

    -- runtime is nil set switch off
    if nullTable(runtime) then
        local ok, err = cache:set(k_switch, -1, expire)
        return false
    end


    local k_divModname      = prefix .. ':'..fields.divModulename
    local k_divDataKey      = prefix .. ':'..fields.divDataKey
    local k_userInfoModname = prefix .. ':'..fields.userInfoModulename

    local ok1, err = cache:set(k_divModname, runtime[fields.divModulename], expire)
    local ok2, err = cache:set(k_divDataKey, runtime[fields.divDataKey], expire)
    local ok3, err = cache:set(k_userInfoModname, runtime[fields.userInfoModulename], expire)

    if areNULL(ok1, ok2, ok3) then return false end

    local ok, err = cache:set(k_switch, 1, expire)
    if not ok then return false end

    return true
end

--
--  fetch upstream of userinfo
--
_M.getUpstream = function(self, userinfo)
    local cache = self.cache
    local info = userinfo
    local upstream

    -- ups will be an actually value or nil
    if info then
        upstream = cache:get(info)
    end

    return upstream
end

_M.setUpstream = function(self, info, upstream)
    local cache = self.cache
    local expire = shdict_expire
    cache:set(info, upstream, expire)
end

return _M
